#include <memory>
#include <unordered_map>
#include <fstream>
#include <signal.h>
using namespace std;
#include "udpServer.hpp"
#include "onlineUser.hpp"
using namespace Server;
const std::string dictTxt = "./dict.txt";
unordered_map<string, string> dict; // 字典
std::string key, value;

static void Usage(string proc)
{
    cout << "Usage:\n\t" << proc << " local_port\n\n";
}

static bool cutString(const string &target, string *key, string *value, const string &sep) // 字符串截取
{
    // string sep=":";
    auto pos = target.find(sep, 0);
    if (pos == string::npos)
    {
        return false;
    }
    *key = target.substr(0, pos);
    *value = target.substr(pos + sep.size());
    return true;
}
static void initDict() // 文件操作
{
    ifstream in(dictTxt, std::ios_base::binary);
    if (!in.is_open()) // 如果文件打开失败
    {
        cerr << "open file " << dictTxt << " error" << endl;
        exit(OPEN_ERR);
    }
    string line;
    while (getline(in, line))
    {
        if (cutString(line, &key, &value, ":")) // 如果截取成功
        {
            dict.insert(make_pair(key, value)); // dict.insert(key,value);
        }
        else // 截取失败
        {
            //...
        }
    }
    in.close();
    cout << "load dict success" << endl;
}
static void debugPrint() // 测试打印函数
{
    for (auto &dt : dict)
    {
        cout << dt.first << "/" << dt.second << endl;
    }
}
// 客户端单词翻译代码
void handMessage(int sockfd, string clientIp, uint16_t clientPort, string message)
{
    // 对客户端的信息进行特定的业务处理，实现了server通信和业务的解耦
    string response_message; // 将查找的字符串保存至此处
    unordered_map<string, string>::iterator iter = dict.find(message);
    if (iter == dict.end())
    {
        response_message = "unknow";
    }
    else
        response_message = iter->second;
    // 服务端向客户端回发数据
    struct sockaddr_in client;
    bzero(&client, sizeof(client));
    client.sin_family = AF_INET;
    client.sin_addr.s_addr = inet_addr(clientIp.c_str());
    client.sin_port = htons(clientPort);
    sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr *)&client, sizeof(client));
}
// 解析客户端上传的命令
void execCommand(int sockfd, string clientIp, uint16_t clientPort, string cmd)
{
    // 对客户端的信息进行特定的业务处理，实现了server通信和业务的解耦
    auto end = cmd.find("rm");
    if (end != string::npos)
    {
        cerr << clientIp << ":" << clientPort << "非法操作" << cmd << endl;
        return;
    }
    string response_message; // 将客户端上传的指令保存至此处
    FILE *fp = popen(cmd.c_str(), "r");
    if (fp == nullptr)
    {
        response_message = cmd + " exec failed";
    }
    char line[1024];
    while (fgets(line, sizeof(line), fp))
    {
        response_message += line; // 读出客户端传入的指令
    }
    pclose(fp);
    // 服务端向客户端回发数据
    struct sockaddr_in client;
    bzero(&client, sizeof(client));
    client.sin_family = AF_INET;
    client.sin_addr.s_addr = inet_addr(clientIp.c_str());
    client.sin_port = htons(clientPort);
    sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr *)&client, sizeof(client));
}

// 聊天室
OnlineUser olUser;
void routeMessage(int sockfd, string clientIp, uint16_t clientPort, string message)
{
    // 上线就从表中新增，下线就减掉
    if (message == "online")
    {
        olUser.addUser(clientIp, clientPort);
    }
    else if (message == "offline")
    {
        olUser.delUser(clientIp, clientPort);
    }
    else if (olUser.isOnline(clientIp, clientPort))
    {
        // 广播消息 -- 发给所有用户
        olUser.broadcastMessage(sockfd, clientIp, clientPort, message);
    }
    else
    {
        // 服务端向客户端回发数据
        string response_message = "请先运行online";
        struct sockaddr_in client;
        bzero(&client, sizeof(client));
        client.sin_family = AF_INET;
        client.sin_addr.s_addr = inet_addr(clientIp.c_str());
        client.sin_port = htons(clientPort);
        sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr *)&client, sizeof(client));
    }
}
void reload(int signo) // 热加载回调函数
{
    (void)signo;
    initDict();
}
int main(int argc, char *argv[]) //./udpServer port
{
    if (argc != 2) // 判断外部传入的参数是否为3？2？
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]); // 需要转uint16_t整型

    // 发送信号，实现文本的热加载
    // 当程序在运行时接收到SIGINT信号时
    // 可以通过重新加载文本内容来更新程序的状态或数据
    // 以实现文本的热加载，无需重启整个程序
    // signal(2, reload);
    // initDict();
    // debugPrint();
    // std::unique_ptr<udpServer> usvr(new udpServer(handMessage, port)); // 在线翻译

    // std::unique_ptr<udpServer> usvr(new udpServer(execCommand,port));// 指令解析

    std::unique_ptr<udpServer> usvr(new udpServer(routeMessage, port)); // 聊天室
    usvr->initServer();
    usvr->start();
    return 0;
}